package com.lanyou.cook.config;

import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.pentaho.di.core.encryption.KettleTwoWayPasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import com.google.common.collect.Maps;

@Configuration
public class ShiroConfig {

	private static final String authenticationQuery = "SELECT PASSWORD, LOGIN_STATUS, ROLE_ID,USER_NAME FROM t_cook_db_user WHERE USER_CODE = ?";
	private static final String userRolesQuery = "SELECT r.role_name FROM t_cook_db_user u" +
			" JOIN t_cook_db_role r ON u.role_id = r.role_id" +
			" WHERE u.user_code = ?";
	private static final String permissionsQuery = "SELECT DISTINCT p.popedom_code FROM t_cook_db_pri p"
			+ " JOIN t_cook_bu_role_pri AS rp ON p.pri_id = rp.pri_id"
			+ " JOIN t_cook_db_role AS r ON r.role_id = rp.role_id" + " WHERE r.role_name = ?";
	
	@Autowired
	private DataSource dataSource;
	
	@Bean
	public JdbcTemplate jdbcTemplate() {
		JdbcTemplate jdbcTemplate = new JdbcTemplate();
		jdbcTemplate.setDataSource(dataSource);
		return jdbcTemplate;
	}
	
	@Bean
	public KettleTwoWayPasswordEncoder kettlePasswordEncoder(){
		return new KettleTwoWayPasswordEncoder();
	}
	
	@Bean	// 需注册为Bean，否则有可能有多实例
	public CredentialsMatcher credentialsMatcher(){
		return new CredentialsMatcher(){
			@Override
			public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
				UsernamePasswordToken upToken = (UsernamePasswordToken) token;
				String tokenPassword = new String(upToken.getPassword());
				
				String  infoPassword = new String((char[])info.getCredentials());
				infoPassword = kettlePasswordEncoder().decode(infoPassword);
				
				boolean result = StringUtils.equals(tokenPassword, infoPassword);
				return result;
				
//				return true;
			}
		};
	}
	
	@Bean	// 需注册为Bean，否则有可能有多实例
	public Realm jdbcRealm(){
		OwnRealm ownRealm = new OwnRealm();
		ownRealm.setDataSource(dataSource);
		ownRealm.setPermissionsLookupEnabled(true);
		ownRealm.setAuthenticationQuery(authenticationQuery);
		ownRealm.setUserRolesQuery(userRolesQuery);
		ownRealm.setPermissionsQuery(permissionsQuery);
		ownRealm.setCredentialsMatcher(credentialsMatcher());
		return ownRealm;
	}
	
	@Bean	// 需注册为Bean，否则有可能有多实例
	public CacheManager cacheManager(){
		return new org.apache.shiro.cache.ehcache.EhCacheManager();
	}
	
	@Bean	// 需注册为Bean，否则有可能有多实例
	public SecurityManager securityManager(){
		DefaultWebSecurityManager securityManager = new org.apache.shiro.web.mgt.DefaultWebSecurityManager(jdbcRealm());
		securityManager.setSessionManager(sessionManager());
		securityManager.setCacheManager(cacheManager());
		return securityManager;
	}
	
//	private SessionDAO sessionDAO(){
//		 SessionDAO sessionDAO = 
//	}
	
	@Bean	// 需注册为Bean，否则有可能有多实例
	public SessionManager sessionManager(){
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(2 * 60 * 60 * 1000);
		sessionManager.setDeleteInvalidSessions(true);
//		sessionManager.setSessionValidationSchedulerEnabled(true);
		return sessionManager;
	}
	
	@Bean
	public ShiroFilterFactoryBean shiroFilter() throws Exception {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		OwnPermissionsAuthorizationFilter ownPermissionsAuthorizationFilter = new OwnPermissionsAuthorizationFilter();
		shiroFilterFactoryBean.setSecurityManager(securityManager());
		shiroFilterFactoryBean.setLoginUrl("/UserLogin.html");
		shiroFilterFactoryBean.setUnauthorizedUrl("/UserLogin.html");
		shiroFilterFactoryBean.setSuccessUrl("/index.html");
		shiroFilterFactoryBean.getFilters().put("perms", ownPermissionsAuthorizationFilter);
		Map<String, String> filterChainDefinition = Maps.newHashMap();
		filterChainDefinition.put("/api/**", "perms");
		filterChainDefinition.put("/index.html", "authc");
		filterChainDefinition.put("/pages/UserManagement/UserRegistration.html", "anon");
		filterChainDefinition.put("/pages/UserManagement/PassRetrieve.html", "anon");
		filterChainDefinition.put("/pages/**", "authc");
		filterChainDefinition.put("/**", "anon");
		
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinition);
		return shiroFilterFactoryBean;
	}
	
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager());
		return advisor;
	}
	
	
	/*@Bean(name={"perms"})
	public OwnPermissionsAuthorizationFilter ownPermissionsAuthorizationFilter(){
		OwnPermissionsAuthorizationFilter ownPermissionsAuthorizationFilter = new OwnPermissionsAuthorizationFilter();
		return ownPermissionsAuthorizationFilter;
	}*/
	
//	@Bean
//	public FilterRegistrationBean shiroFilter() throws Exception{
//		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
//		registrationBean.setFilter((Filter)shiroFilterFactoryBean().getObject());
//		return registrationBean;
//	}
	
	
	
}
